/*
   
# 模范class

- c++提供class，让程序员可以增加新的数据类型。
- 这些新的数据类型必须具有和基本类型（想一下int和string，尤其是string）一样的特性，这样才能：
  - 支持基本的操作，如+，=，...。
  - 支持I/O操作
  - 支持STL中的算法和容器。

- 这样的class，就是模范class。下面的例子给出了定义模范class的基本要素。
- 注意：一般建议class中不要包含指针成员，这时就可以不定义拷贝构造函数和重载赋值运算符（编译器会默认实现）。
    
*/
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <iomanip>
using namespace std;
class Student
{
     private:
         int id;
         string name;
         int score1,score2;
         int sum;
     public:
         /*
        1 这个叫无参数构造函数。
        2 有了这个构造函数，就可以这样创建对象：
            Student s;  
            Student * p = new Student[10];   
        3 如果你一个构造函数都没定义，编译器会自动给你加一个和这个一模一样的。
           因为你一般都会定义其他的构造函数，所以强烈建议像这样定义。
         */
         Student()   
         {
         }
         /*
         1 这是一个普通构造函数
         2 有了这个构造函数，就可以这样创建对象：
            Student s(10,"zhangsan");  
            Student * p = new Student(10,"zhangsan");  
            Student s2 = {10,"zhangsan"}; //c++11
            vector<Student> v={{10,"zhangsan"},{11,"lisi"}}; //c++14
         3 根据对象初始化的需要，可以定义多个。
         */
         Student(int pid,string pname)
         {
             id = pid;
             name = pname;
         }
         /*
         1 这个很普通，就是class的方法（或者叫类的函数）。
         2 不能没有她，因为这几个属性都是private。
         */
         void setScore(int pscore1,int pscore2)
         {
             score1 = pscore1;
             score2 = pscore2;
             sum = score1 + score2;   
         }
         /*
         1 这是对<<和>>运算符重载。
         2 有了它，就可以这样输入和输出对象:
            Student s; cin>>s; cout<<s;
         3 强烈建议：不要忘了“&”符号，一个都不能少。不要问我怎么知道的:(
         */
        friend istream & operator>>(istream & in, Student& s)
        {
            in>>s.id>>s.name>>s.score1>>s.score2;
            s.sum = s.score1 + s.score2;
            return in;
        }
        friend ostream & operator<<(ostream & out, Student& s)
        {
            out<<s.id<<"("<<s.sum<<"):  "<<setw(15)<<s.name<<setw(5)<<s.score1<<setw(5)<<s.score2<<endl;
            return out;
        }
         /*
         1 这是对关系运算符<重载。
         2 有了它。就可以这样使用对象(第三步):
            Student s1(10,"tom"); String s2(11,"john"); cout<<(s1<s2); 
         3 有了它，algorithm中的sort,max,min,min_element等就可以用了。
         4 强烈建议，根据排序要求，进行重载。
         */
        friend bool operator<(const Student & s1,const Student & s2)
        {
            if(s1.sum < s2.sum)
                return true;
            else
                return false;
        }
         /*
         1 这个叫拷贝构造函数。
         2 有了这个构造函数，就可以这样创建对象（下面的第2步）：
            Student s1(10,"zhangsan");  
            Student s2(s1);
         3 有了这个构造函数，你就可以把这个对象传给函数做参数。
         4 有了这个构造函数，你就可以把这个对象作为函数的返回值。
         5 如果你不定义这个构造函数，编译器会帮你加一个，和这个一模一样。
         6 强烈建议你们不要定义。
         */
        /*
         Student(const Student & s)
         {
             id = s.id;
             name = s.name;
             score1 = s.score1;
             score2 = s.score2;
             sum = s.sum;
         }
         */
         /*
         1 这是对赋值运算符=重载。
         2 有了它。就可以这样使用对象(下面第二步):
            Student s1(10,"tom"); String s2 = s1; 
         3 如果你不重载这个运算符，编译器会帮你加一个，和这个一模一样。
         4 强烈建议你们不要重载。
         5 这个不能作为友元函数来重载，而是类的成员方法，前面不能有friend。 
         */
        /*
        void operator=(const Student & s1)
        {
            id = s1.id; name = s1.name; score1 = s1.score1; score2 = s1.score2; sum = s1.sum;
        }
        */
};
int main()
{
    /*
    vector<Student> vs = {{1,"zhansan"},{2,"lisi"}};  //-std=c++14
    vs[0].setScore(100,99);
    vs[1].setScore(99,88);
    */
    vector<Student> vs;
    int N;
    cin>>N;
    for(int i = 0; i<N; i++)
    {
        Student temp;
        cin>>temp;
        vs.push_back(temp);
    }
      
    cout<<setw(20)<<internal<<"***list***"<<endl;
    for(auto ele:vs)
        cout<<ele;
    
    cout<<setw(20)<<internal<<"***highest score***"<<endl;
    auto it = max_element(vs.begin(),vs.end());
    cout<<*it;
   
    cout<<setw(20)<<internal<<"***sort***"<<endl;
    sort(vs.begin(),vs.end());
    for(auto ele:vs)
        cout<<ele;
    
    cout<<setw(20)<<internal<<"***reverse***"<<endl;
    reverse(vs.begin(),vs.end());
    for(auto ele:vs)
        cout<<ele;
}